/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package desarrollosoft.ghce.servicio.implementaciones;

import desarrollosoft.ghce.dao.interfaces.IBajaLogicaProfesionalDAO;
import desarrollosoft.ghce.dao.interfaces.IEspecialidadDAO;
import desarrollosoft.ghce.dao.interfaces.IProfesionalDAO;
import desarrollosoft.ghce.dao.interfaces.ISexoDAO;
import desarrollosoft.ghce.dao.interfaces.ITipoDocumentoDAO;
import desarrollosoft.ghce.entidades.BajaLogicaProfesional;
import desarrollosoft.ghce.entidades.Especialidad;
import desarrollosoft.ghce.entidades.Profesional;
import desarrollosoft.ghce.entidades.Sexo;
import desarrollosoft.ghce.entidades.TipoDocumento;
import desarrollosoft.ghce.servicio.interfaces.IServicioProfesionales;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author ariel
 */
@Service("servicioProfesionales")
public class ServicioProfesionales implements IServicioProfesionales {

    @Autowired
    @Qualifier("tipoDocumentoDAO")
    private ITipoDocumentoDAO tipoDocumentoDAO;
    
    @Autowired
    @Qualifier("sexoDAO")
    private ISexoDAO sexoDAO;
    
    @Autowired
    @Qualifier("profesionalDAO")
    private IProfesionalDAO profesionalDAO;
    
    @Autowired
    @Qualifier("especialidadDAO")
    private IEspecialidadDAO especialidadDAO;
    
    @Autowired
    @Qualifier("bajaLogicaProfesionalDAO")
    private IBajaLogicaProfesionalDAO bajaLogicaProfesionalDAO; // falta implementacion
    
    @Autowired
    private ShaPasswordEncoder passwordEncoder;
    
    @Override
    public Profesional buscarPorNombreUsuario(String nombreUsuario) throws Exception {
        return profesionalDAO.buscarPorNombreUsuario(nombreUsuario);
    }
    
    @Override
    public List<Profesional> buscarTodosProfesionales() {
        return profesionalDAO.buscarTodosProfesionales();
    }

    @Override
    public List<Especialidad> buscarTodasEspecialidades() {
        return especialidadDAO.buscarTodasEspecialidades();
    }

    @Override
    public List<TipoDocumento> obtenerTiposDocumento() {
        return tipoDocumentoDAO.obtenerTodosTipoDocumento();
    }

    @Override
    public List<Sexo> obtenerTodosSexo() {
        return sexoDAO.obtenerTodosSexo();
    }

    @Override
    public List<String> obtenerDatosBuscables() {
        List<String> lista = new ArrayList<>();
        
        lista.add("Apellido");
        lista.add("Numero Documento");
        lista.add("Nombre de Usuario");
        
        return lista;
    }

    @Override
    public List<String> obtenerTodosRoles() {
        List<String> lista = new ArrayList<>();
        
        lista.add("Profesional");
        lista.add("Administrador");
        
        return lista;
    }

    @Override
    @Transactional
    public void crearProfesional(Profesional profesional) throws Exception {
        String expresion = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
        if (profesional.getMail() != null && !profesional.getMail().matches(expresion)) {
            throw new Exception("Asegurese de ingresar un mail valido");
        }
        String nombreUsuario = profesional.getNombreUsuario();
        String contraseniaHasheada = generarContraseniaHasheada(nombreUsuario, nombreUsuario);
        profesional.setContrasenia(contraseniaHasheada);
        profesionalDAO.crearProfesional(profesional);
    }

    @Override
    @Transactional
    public void modificarProfesional(Profesional profesional) throws Exception {
        String expresion = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
        if (profesional.getMail() != null && !profesional.getMail().matches(expresion)) {
            throw new Exception("Asegurese de ingresar un mail valido");
        }
        String nombreUsuario = profesional.getNombreUsuario();
        String contraseniaHasheada = generarContraseniaHasheada(nombreUsuario, nombreUsuario);
        profesional.setContrasenia(contraseniaHasheada);
        profesionalDAO.modificarProfesional(profesional);
    }

    @Override
    @Transactional
    public void bajaLogicaProfesional(Profesional profesional, String causas, Date fechaSuceso) throws Exception {
        if (causas == null || fechaSuceso == null) {
            throw new Exception("Ni las Causas ni la Fecha del Suceso pueden estar vacias");
        }
        
        BajaLogicaProfesional bajaLogica = new BajaLogicaProfesional();
        bajaLogica.setCausas(causas);
        bajaLogica.setFechaSuceso(fechaSuceso);
        
        bajaLogicaProfesionalDAO.crearBajaLogica(bajaLogica);
        profesional.setBajaLogicaProfesional(bajaLogica);
        profesionalDAO.modificarProfesional(profesional);
    }

    @Override
    public List<Profesional> buscarProfesionales(String dato, String tipoDato) {
        return profesionalDAO.buscarProfesionales(dato, tipoDato);
    }

    @Override
    public List<Especialidad> buscarEspecialidades(String nombre) {
        return especialidadDAO.buscarPorNombre(nombre);
    }

    @Override
    @Transactional
    public void reactivarProfesional(Profesional profesional) throws Exception {
        if (profesional.getBajaLogicaProfesional() == null) {
            throw new Exception("El profesional que intenta reactiva ya esta activo");
        }
        BajaLogicaProfesional bajaLogica = profesional.getBajaLogicaProfesional();
        profesional.setBajaLogicaProfesional(null);
        profesionalDAO.modificarProfesional(profesional); // guardo el profesional, sin baja logica
        bajaLogicaProfesionalDAO.eliminarBajaLogica(bajaLogica); // elimino la baja logica
    }

    @Override
    @Transactional
    public void resetearContrasenia(Profesional profesional) throws Exception {
        if (estaReseteado(profesional)) {
            throw new Exception("El profesional ya tiene su contrasenia reseteada");
        }
        String nombreUsuario = profesional.getNombreUsuario();
        String contraseniaHasheada = generarContraseniaHasheada(nombreUsuario, nombreUsuario);
        profesional.setContrasenia(contraseniaHasheada);
        profesionalDAO.modificarProfesional(profesional);
    }
    
    @Override
    @Transactional
    public void ingresaNuevaContrasenia(Profesional profesional, String contrasenia, String contraseniaRepetida) throws Exception {
        if (!estaReseteado(profesional)) {
            throw new Exception("El profesional no esta reseteado!, comuniquese con un administrador del sistema");
        }
        if (!contrasenia.equals(contraseniaRepetida)) {
            throw new Exception("Las contrasenias no son iguales");
        }
        if (contrasenia.equals(profesional.getNombreUsuario())) {
            throw new Exception("Su contrasenia debe ser distinta a su Nombre de Usuario");
        }
        String contraseniaHasheada = generarContraseniaHasheada(contrasenia, profesional.getNombreUsuario());
        profesional.setContrasenia(contraseniaHasheada);
        profesionalDAO.modificarProfesional(profesional);
    }

    @Override
    public boolean estaReseteado(Profesional profesional) {
        // si nombre de usuario, hasheado con nombre de usuario como sal, es igual a contraseña devolver true, sino false
        String nombreUsuario = profesional.getNombreUsuario();
        String contraseniaGenerada = generarContraseniaHasheada(nombreUsuario, nombreUsuario);
        
        if (profesional.getContrasenia().equals(contraseniaGenerada)) {
            return true;
        }
        return false;
    }
    
    private String generarContraseniaHasheada(String contraseniaPlana, String sal) {
        String contraseniaHasheada = passwordEncoder.encodePassword(contraseniaPlana, sal);
        return contraseniaHasheada;
    }

    @Override
    public Profesional obtenerProfesional(String nombreUsuarioActual) throws Exception {
        return profesionalDAO.buscarPorNombreUsuario(nombreUsuarioActual);
    }

    @Override
    @Transactional
    public void cambiaContrasenia(Profesional profesional, String contrasenia, String contraseniaRepetida) throws Exception {
        if (!contrasenia.equals(contraseniaRepetida)) {
            throw new Exception("Las contrasenias no son iguales");
        }
        if (contrasenia.equals(profesional.getNombreUsuario())) {
            throw new Exception("Su contrasenia debe ser distinta a su Nombre de Usuario");
        }
        String contraseniaHasheada = generarContraseniaHasheada(contrasenia, profesional.getNombreUsuario());
        profesional.setContrasenia(contraseniaHasheada);
        profesionalDAO.modificarProfesional(profesional);
    }
}
